package com.app.web.filters;

import com.app.common.ResponseResult;
import com.app.pojo.User;
import com.app.utils.UtilTools;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * Copyright (C) @2020 fgwang.660@gmail.com
 *
 * @author witt
 * @version 1.0
 * @className AppFilter
 * @date 2020-06-14 12:30
 * @description 项目过滤器
 * 		<p>
 * 		处理编码，校验登录等 我就是一个筛子，位于浏览器和服务器中间  一层一层的往下筛
 */

@WebFilter (filterName = "AppFilter", urlPatterns = "/*")
public class AppFilter implements Filter {

	/**
	 * 花名册(也叫白名单)，只要在我这个册子上记录了这些 URL ，不用登陆  也是可以直接访问的
	 */
	private static final String[] roster = new String[] {
			// 首页
			"index.jsp",
			// 消息显示页面
			"message.jsp",
			// UI 框架
			"bootstrap-3.3.7",
			// bootstrap 依赖的JS框架
			"jQuery",
			"js",
			"css",
			"login.jsp",
			"register.jsp",
			"images",
			"/login",
			"/register",
			"/reset-password"
	};

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {


		System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ------  AppFilter ------   >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

		/**
		 * 浏览器发出的请求，半路开始过滤，处理完了，要么放过去，要么  滚回去
		 */

		// 1.所有请求全部统一为一种编码
		servletRequest.setCharacterEncoding("UTF-8");

		// 2.强转 请求和响应对象  父类引用指向子类对象
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;

		// 3.获取服务器为浏览器创建的会话（看登录逻辑，会话里做了什么）
		HttpSession session = request.getSession();

		// 4.不管有没有，从会话里拿出来一个user,没有就是 NULL
		Object userToken = session.getAttribute("user");

		// 4 真的是个NULL  或者 [不是] 本系统放进去的类型 [并且]  你请求的资源还不在花名册中  那你赶紧滚回去登录  你没权限访问
		if ((UtilTools.isEmpty(userToken) || ! (userToken instanceof User)) && ! this.check(request.getServletPath())) {

			// 消息页面提示  完成后  1 跳转
			ResponseResult.warn(request, response, "登录提示！", "用户未登录或登录状态已失效，请重新登录后执行此操作！", 3f, "login.jsp");

			// 4.1 结束方法 不要执行后面的代码 (response已经回到浏览器了)
			return;
		}

		// 3.1.9 上面都未通过

		// 3.1.9.1 不管请求有没有处理，都必须放过去
		chain.doFilter(request, response);

		// 响应回到客户端前(处理一下)
		System.out.println(" -------------------------------- HTTP response filter ..... --------------------------------------------");

		// 响应给浏览器时处理编码 (请求到达客户端前 处理一下)
		servletResponse.setCharacterEncoding("UTF-8");
	}

	/**
	 * 检查资源是否放行
	 *
	 * @param path
	 * @return
	 */
	private boolean check(String path) {

		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> filter URL : [" + path + "]   ");

		/**
		 * 这种情况几乎不存在，以防万一
		 */
		if (UtilTools.isEmpty(path)) return false;

		/**
		 * 如果配置的没有项目名，就直接是根目录，根目录直接放过去  不让永远打不开页面
		 */
		if ("/".equals(path)) {
			return true;
		}

		/**
		 * 恰好和我花名册上的匹配，放过去，比如 花名册:index.jsp ,path:index.jsp
		 */
		if (UtilTools.contains(roster, path)) return true;

		/**
		 * 路径以花名册上的开头就放行
		 */
		return UtilTools.contains(roster, path.split("[/]")[1]);
	}


}
